package com.fang.study_demo01.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author Bernie_xin
 * @create 2020/12/3 20:41
 **/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        // 自动创建表,第一次执行会创建，以后要执行就要删除掉！
        // jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置没有权限访问跳转的自定义页面
        // http.exceptionHandling().accessDeniedPage("/unAuth.html");


        http.formLogin()        //开启拦截跳转页面，没有设置自定义页面的话，security默认使用自己的
                // .loginPage("/login.html")       //在这里设置自定义的登录页面
                .loginProcessingUrl("/test/indexs")     //设置登录的请求地址
                // .successForwardUrl("/test/indexs")       //登录成功之后的跳转路径
                // .failureForwardUrl("/test/fail")                     //登录失败之后的跳转路径

                .and().authorizeRequests()          //开启请求认证
                .antMatchers("/", "/test/hello", "/user/login").permitAll()     //不需要认证的请求
                // .anyRequest().authenticated()       //其他请求都需要认证

                //.antMatchers("/test/index").hasAuthority("admin") //表示当前用户具有admin权限才能访问
                //表示当前用户具有admin或者manager权限就能访问
                //.antMatchers("/test/indexs").hasAnyAuthority("admin","manager")


                // .antMatchers("/test/indexs").hasRole("sale")
                .antMatchers("/test/indexs").hasAnyRole("sale","manger","admin")

                .and().rememberMe().tokenRepository(persistentTokenRepository()) //设置记住我，操作数据库对象
                .tokenValiditySeconds(60)       //设置有效时长，单位秒
                .userDetailsService(userDetailsService)

                .and().csrf().disable();        //关闭csrf防护

        http.logout().logoutUrl("/logout")  // 开启退出，设置退出接口
                .logoutSuccessUrl("/test/hello");       //设置退出成功的请求地址
    }


    //授权
    // @Override
    // protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //
    //     auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
    //             .withUser("fang").password(new BCryptPasswordEncoder().encode("123123")).roles("vip1", "vip2", "vip3")
    //             .and()
    //             .withUser("root").password(new BCryptPasswordEncoder().encode("123123")).roles("vip1", "vip2")
    //             .and()
    //             .withUser("guest").password(new BCryptPasswordEncoder().encode("123123")).roles("vip1");
    //
    // }

    @Autowired
    private UserDetailsService userDetailsService;

    // 授权
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        // auth.inMemoryAuthentication().withUser("tom").password(bCryptPasswordEncoder.encode("123")).roles("admin");
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


}
